/*
 *  pwm.c
 *
 *  Created on: 2017年9月13日
 *      Author: WEY
 */
#include "2440addr.h"
#include "serialcom.h"
#include "pwm.h"
#include "rtc.h"
enum{
	SOUND_LEVEL0=0,
	SOUND_LEVEL1,
	SOUND_LEVEL2,
	SOUND_LEVEL_COUNT,
};
enum{
	SOUND_A=0,
	SOUND_B,
	SOUND_C,
	SOUND_D,
	SOUND_E,
	SOUND_F,
	SOUND_G,
	SOUNT_TUNE_COUNT,
};
enum{
	SOUND_PITCH_1=0,
	SOUND_PITCH_2,
	SOUND_PITCH_3,
	SOUND_PITCH_4,
	SOUND_PITCH_5,
	SOUND_PITCH_6,
	SOUND_PITCH_7,
	SOUNT_PITCH_COUNT,
};

const int g_music_fre_table1[SOUNT_TUNE_COUNT][SOUNT_PITCH_COUNT]={
		221,248,278,294,330,371,416,
		248,278,294,330,371,416,467,
		131,147,165,175,196,221,248,
		147,165,175,196,221,248,278,
		165,175,196,221,248,278,312,
		175,196,221,234,262,294,330,
		196,221,234,262,294,330,371,
};//SOUND_LEVEL0
const int g_music_fre_table2[SOUNT_TUNE_COUNT][SOUNT_PITCH_COUNT]={
		441,495,556,589,661,742,833,
		495,556,624,661,742,833,935,
		262,294,330,350,393,441,495,
		294,330,350,393,441,495,556,
		330,350,393,441,495,556,624,
		350,393,441,495,556,624,661,
		393,441,495,556,624,661,742,
};//SOUND_LEVEL1
const int g_music_fre_table3[SOUNT_TUNE_COUNT][SOUNT_PITCH_COUNT]={
		882,990,1112,1178,1322,1484,1665,
		990,1112,1178,1322,1484,1665,1869,
		525,589,661,700,786,882,990,
		589,661,700,786,882,990,1112,
		661,700,786,882,990,1112,1248,
		700,786,882,935,1049,1178,1322,
		786,882,990,1049,1178,1322,1484,
};
const int g_musicData[]={
   0x101,0x102,0x103,0x104,0x105,0x106,0x107,0x0,0x0,
   0x111,0x112,0x113,0x114,0x115,0x116,0x117,0x0,0x0,
   0x121,0x122,0x123,0x124,0x125,0x126,0x127,0x0,0x0,
};

/*
const int g_musicData[]={
 0x0,0x0,
 0x215,0x215,

 0x125,0x123,0x121,
 0x117,0x116,0x116,
 0x0,0x0,0x224,0x224,
 0x123,0x121,0x122,
 0x121,0x121,
 0x215,0x215,
 0x116,0x115,0x121,
 0x117,0x117,0x215,0x215,
 0x116,0x115,0x122,
 0x121,0x121,0x215,
 0x117,0x116,0x116,
 0x0,0x0,0x224,0x224,
 0x123,0x121,0x122,
 0x121,0x121,0x215,0x215,

 0x125,0x123,0x121,
 0x117,0x116,0x116,
 0x0,0x0,0x224,0x224,
 0x123,0x121,0x122,
 0x121,0x121,
 0x215,0x215,
 0x116,0x115,0x121,
 0x117,0x117,0x215,0x215,
 0x116,0x115,0x122,
 0x121,0x121,0x215,
 0x117,0x116,0x116,
 0x0,0x0,0x224,0x224,
 0x123,0x121,0x122,
 0x121,0x121,0x215,0x215,

 0x121,0x121,0x215,0x215,
 0x125,0x123,0x121,
 0x117,0x116,0x116,
 0x0,0x0,0x224,0x224,
 0x123,0x121,0x122,
 0x121,0x121,0x121,
 0x0,
};*/
int curTune=SOUND_A;
int currentIndex=0;
int isLedSholdOn=0;
int duraCount;
//一拍时间,单位s
#define ONEBEATTIME 1
#define DEFAULTFREQUENCY 1000

int calTCount(int tune,int index,int *tcb,int *tcm,int *duraCount)
{
	int data=g_musicData[index];
	int soundLv=((data>>4)& 0xF);
	int pitch=(data &0xF);
	int beat=((data>>8)&0xF);
	int fre;
	if(pitch==0){
		*tcb=250000/DEFAULTFREQUENCY;
		*duraCount=(int)(DEFAULTFREQUENCY*ONEBEATTIME);
		*tcm=0;
		return DEFAULTFREQUENCY;
	}else{
		switch(soundLv){
		case SOUND_LEVEL0:
			fre=g_music_fre_table1[tune][pitch-1];
			break;
		case SOUND_LEVEL1:
			fre=g_music_fre_table3[tune][pitch-1];
			break;
		case SOUND_LEVEL2:
			fre=g_music_fre_table3[tune][pitch-1];
			break;
		}
		*tcb=(int)(250000/(fre+0.0)+0.5);
		*tcm=*tcb>>1;
		*duraCount=(int)(fre*ONEBEATTIME/beat);
		return fre;
	}
}
void __irq timer0_isr(void)
{
	int tcb,tcm;
	DateTime dt;
	duraCount--;
	if(duraCount<=0){
		isLedSholdOn ^=1;
		currentIndex++;
		if(currentIndex>=sizeof(g_musicData)/sizeof(int)){
			currentIndex=0;
			curTune++;
			if(curTune>=SOUNT_TUNE_COUNT){
				led1_on;
				led2_on;
				led3_on;
				led4_on;
				pwm_stop();
			}
		}
		calTCount(curTune,currentIndex,&tcb,&tcm,&duraCount);
		rTCNTB0=tcb;
		rTCMPB0=tcm;
		rtc_get(&dt);
		Uart_Printf("%d-%d-%d %d:%d:%d\n",dt.year,dt.month,dt.day,dt.hour,dt.min,dt.sec);
	}
	if(isLedSholdOn){
		led1_on;
	}
	else{
		led1_off;
	}

	ClearPending(1<<10);
}

void pwm_init(void){
		int tcb0,tcm0;
		currentIndex=0;
		led1_off;

		calTCount(SOUND_C,currentIndex,&tcb0,&tcm0,&duraCount);

		// 配置为TOUT0引脚
		rGPBCON &= ~1;
		rGPBCON |= 1<<1;
		// 初始化定时器T0
		//
		rTCFG0 &= ~(0xff);
		rTCFG0 |= 99;

		rTCFG1 &= ~((0xf)<<20);
		rTCFG1 &= ~(0xf);

		rTCNTB0=tcb0;
		rTCMPB0=tcm0;

		rTCON &= ~(1<<4);//死区关闭
		rTCON |= 1<<1;//手动更新

		rINTMSK &=~(1<<10);//定时器中断开

		pISR_TIMER0=(unsigned int)timer0_isr;
		unsigned int data=rTCON;
		data &= ~(1<<1 |1<<2);
		data |= (1|1<<3);
		rTCON =data;
}

void pwm_setfre(int fre){
	static int flag=0;
	if(flag){
		flag=0;
		led1_on;
	}else{
		led1_off;
		flag++;
	}
	// 配置为TOUT0引脚
	rGPBCON &= ~1;
	rGPBCON |= 1<<1;
	// 初始化定时器T0
	rTCFG0 &= ~(0xff);
	rTCFG0 |= 99;

	rTCFG1 &= ~((0xf)<<20);
	rTCFG1 &= ~(0xf);

	rTCNTB0=250000/fre;
	rTCMPB0=rTCNTB0>>1;

	rTCON &= ~(1<<4);//死区关闭
	rTCON |= 1<<1;//手动更新

	unsigned int data=rTCON;
	data &= ~(1<<1 |1<<2);
	data |= (1|1<<3);
	rTCON =data;
}

void pwm_stop(void){
	rTCON &=~1;
	rGPBCON &= ~3;			//set GPB0 as output
	rGPBCON |= 1;
	rGPBDAT &= ~1;
	Uart_Printf("beeper stoped\n");
}
